#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "detail/bmock_in_arg_val.hpp"
#include "detail/bmock_test_control_tools.hpp"
#include <sstream>

namespace bmock {
	static const control_tools_ptr tl(new test_control_tools());
	static const char              name[] = "arg";
	static const int               val    = 127;
	static const std::string            s_val  = boost::lexical_cast<std::string>(val);
	static void f() {}

	BOOST_AUTO_TEST_CASE(test_simple_arg_val) {
		const arg_val_ptr p_val(make_in_arg_val(name,val));
		const arg_val_str expected(s_val,"");
		arg_checker       al(tl);
		bool              result = true;

		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected,p_val->get_value(al));
	}

	BOOST_AUTO_TEST_CASE(test_print_in_arg_val) {
		const arg_val_ptr p_val(make_in_arg_val(name,val));
		std::ostringstream        os;
		const std::string      expected = "IN(\""+s_val+"\")";

		BOOST_CHECK_NO_THROW(p_val->print(os));
		BOOST_CHECK_EQUAL(expected,os.str());
	}

	BOOST_AUTO_TEST_CASE(test_const_ptr_arg_val) {
		const arg_val_ptr p_val(make_in_arg_val(name,&val));
		const arg_val_str expected(s_val,"");
		arg_checker       al(tl);
		bool              result = true;

		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected,p_val->get_value(al));
	}

	BOOST_AUTO_TEST_CASE(test_ptr_arg_val) {
		int               val1 = val;
		const arg_val_ptr p_val(make_in_arg_val(name,&val1));
		const arg_val_str expected(s_val,"");
		arg_checker       al(tl);
		bool              result = true;

		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected,p_val->get_value(al));
	}

	typedef struct test_data_type *test_handle;
#ifdef _MSC_VER
	const arg_val_str expected_ptr_string(std::string("0x") + WIN64_EXTRA_ZEROS + "000000AB","");
#else
	const arg_val_str expected_ptr_string("0xab","");
#endif

	BOOST_AUTO_TEST_CASE(test_in_ptr_arg_val) {
		test_handle       th = (test_handle)0xAB;
		const arg_val_ptr p_val(make_in_ptr_arg_val(name,th));
		arg_checker       al(tl);
		bool              result = true;
		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected_ptr_string));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected_ptr_string,p_val->get_value(al));
	}

	typedef void *void_handle;
	BOOST_AUTO_TEST_CASE(test_in_void_ptr_arg_val) {
		void_handle       th = (void_handle)0xAB;
		const arg_val_ptr p_val(make_in_ptr_arg_val(name,th));
		arg_checker       al(tl);
		bool              result = true;
		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected_ptr_string));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected_ptr_string,p_val->get_value(al));
	}

	BOOST_AUTO_TEST_CASE(test_const_in_void_ptr_arg_val) {
		const void *const th = (const void *const)0xAB;
		const arg_val_ptr p_val(make_in_ptr_arg_val(name,th));
		arg_checker       al(tl);
		bool              result = true;
		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected_ptr_string));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected_ptr_string,p_val->get_value(al));
	}

	struct test_custom_ignored_type {
		int i;
	};
}

namespace std {
	std::ostream &operator <<(std::ostream &os,const bmock::test_custom_ignored_type *) {
		os << "<IGNORE>";
		return os;
	}
}

namespace bmock {
	BOOST_AUTO_TEST_CASE(test_in_custom_ptr_arg_val) {
		const test_custom_ignored_type *const th = (const test_custom_ignored_type *const)0xAB;
		const arg_val_ptr p_val(make_in_ptr_arg_val(name,th));
		const arg_val_str expected(BMOCK_HEX_PREFIX "<IGNORE>","");
		arg_checker       al(tl);
		bool              result = true;
		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected,p_val->get_value(al));
	}

	BOOST_AUTO_TEST_CASE(test_in_function_ptr_arg_val) {
		void (*th) = reinterpret_cast<void*>(f);
		const arg_val_ptr p_val(make_in_ptr_arg_val(name,&f));
		const arg_val_str expected(BMOCK_HEX_PREFIX+boost::lexical_cast<std::string>(th),"");
		arg_checker       al(tl);
		bool              result = true;
		al.set_location(location(__FILE__,__LINE__+1));
		BOOST_CHECK_NO_THROW(result = p_val->validate(al,expected));
		BOOST_CHECK(!result);
		BOOST_CHECK_EQUAL(expected,p_val->get_value(al));
	}

	BOOST_AUTO_TEST_CASE(test_in_arg_val_for_coverage)
	{
		BOOST_CHECK_NO_THROW(f())
	}
}
